<?php

namespace App\Recharge\Service;

use App\Models\NsSupplierGoods;
use App\Models\XnMyyGoodsInterconnection;
use Exception;
use Throwable;
use App\Recharge\Library;
use Psr\Log\LoggerInterface;
use Illuminate\Support\Facades\Log;
use App\Models\H5CombinedOrders;
use App\Recharge\Bean\RequestResultBean;
use App\Models\InterfaceConfiguration;
use App\Recharge\Exceptions\SuspensionOfEnforcement;
use App\Recharge\Exceptions\CyclePunch\CyclePunchException;


class CombinationProductsService extends BaseService
{
    /**
     * 执行操作
     *
     * @return void
     */
    public function execute(): void
    {
        try {
            // 主商品
            $this->mainGood();
            // 获取子商品
            $this->getChildProduct();
            // 全部失败了
            if ($this->eachChildren()) {
                throw new CyclePunchException('全部失败了', true);
            }
        } catch (Throwable $e) {
            if ($e instanceof CyclePunchException && $e->isOrderFailed()) {
                $this->allOrdersFailed($e->getMessage());
            }
            $this->log()->error('组合商品消费其他失败', ['ding' => true, 'data' => $this->bean->toArray(), 'trace' => error2array($e)]);
        }
    }

    /**
     * @return bool 是否全部失败了 true=是 那么要结束订单 false的话不用 等待回调
     */
    public function eachChildren(): bool
    {
        $allFailed = true;
        // 循环
        foreach ($this->bean->getChildren() as $i => $child) {
            // 订单号
            $tradeNo = $this->bean->getOrderNo() . '-'. ($i + 1);
            try {
                //电信过滤
                //$this->telecomFiltering($child);
                // 获取api
                $api = $this->api($child);
                // 检测配置
                $config = $this->cg->supplierApiConfigCheck($api);
                // 价格筛选
                $this->goodLogic->goodPriceToFilter($child['price'], $child, $api, $config);
                // 获取apiInterface
                $interface = $this->obtainApiInterface($api);
                // 生成bean
                $bean = $this->cg->makeBasicInformation($api, $this->order, $child, $config)->setOrderNo($tradeNo);
                // 请求
                $baseBean = Library::executeRecharge($interface, httpClient(), $api, $bean);
                // 只要有一个成功的就不是都失败
                if ($baseBean->isResult() && $allFailed) {
                    $allFailed = false;
                }
            } catch (SuspensionOfEnforcement $e) {
                $baseBean = new RequestResultBean();
                $baseBean->setErrorMessage($e->getMessage());
                $this->log()->error('子商品消费失败', [
                    'child'     => $child,
                    'order'     => $this->order->toArray(),
                    'error'     => error2array($e),
                ]);
            } finally {
                $this->generateOrders($baseBean, $child, $tradeNo, $api ?? null);
            }
        }
        return $allFailed;
    }

    /**
     * 保存循环订单
     *
     * @param RequestResultBean $result
     * @param array $child
     * @param string $trade_no
     * @param InterfaceConfiguration|null $api
     * @return bool
     */
    function generateOrders(RequestResultBean $result, array $child, string $trade_no, ?InterfaceConfiguration $api = null): bool
    {
        try {
            $state = $result->isResult() ? 0 : 2;
            $data = [
                'order_no'          => $this->order->orderNum,
                'trade_no'          => $trade_no,
                'pid'               => $this->bean->getGood()->id,
                'gid'               => $child['id'],
                'good_name'         => $child['goodsName'],
                'g_code'            => $child['goodsId'],
                'recharge_num'      => $this->order->rechargeNum,
                'unit_price'        => $child['unitPrice'],
                'state'             => $state,
                'supplier_status'   => $child['Supplier_status'],
                'error_msg'         => $result->getErrorMessage(),
                'create_time'       => date('Y-m-d H:i:s'),
                'error_time'        => $state == 2 ? date('Y-m-d H:i:s') : null,
            ];
            if ($result->isSendApi()) {
                $request = $result->getRequest();
                $data = array_merge($data, [
                    'request_url'   => $result->getUrl(),
                    'request_header'=> array2json($result->getOptions()),
                    'request'       => is_array($request) ? array2json($request) : $request,
                    'sync_msg'      => $result->getResponse(),
                    'sync_time'     => $data['create_time']
                ]);
            }
            if ($result->isResult() && !is_null($api)) {
                // 保存第三方订单号
                if ($api->trade_no_key) {
                    $data['other_order'] = data_get($result->getFormatResponse(), $api->trade_no_key, '');
                }
            }
            // 新增
            if (!H5CombinedOrders::insert($data)) {
                throw new Exception("保存组合订单失败");
            }
        } catch (Throwable $e) {
            $this->log()->error('组合商品保存第三方下单失败:' . $e->getMessage(), [
                'ding'  => true,
                'bean'  => $this->bean->toArray(),
                'trace' => error2array($e)
            ]);
        }
        return $result->isResult();
    }

    /**
     * 获取子商品
     *
     * @return void
     * @throws CyclePunchException
     */
    public function getChildProduct(): void
    {
        $children = [];
        // 获取关联信息
        $relations = XnMyyGoodsInterconnection::query()->where('id',$this->order->goodsId)->value('g_id');
        // 为空不继续
        if (!$relations) {
            goto end;
        }
//        $this->bean->setRelations($relations);
        $relations = explode(',',$relations);
        // 便利关系
        foreach ($relations as $relation) {

            if ($child = NsSupplierGoods::query()->where('id',$relation)->first()) {
                $children[] = $child->toArray();
            }
        }
        // 返回
        end: $this->bean->setChildren($children);
        // 为空的话失败
        if (empty($children)) {
            throw new CyclePunchException('未查找到子商品', true);
        }
    }

    /**
     * @return LoggerInterface
     */
    protected function log(): LoggerInterface
    {
        return Log::channel('zuhe');
    }
}
